/*---------------------------------------------------------------------------*\
 This file is part of the Fab@Home Project.
 Fab@Home operates under the BSD Open Source License.

 Copyright (c) 2009, Karl Gluck (kwg8@cornell.edu)
 
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the <organization> nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNERS OR CONTRIBUTORS BE LIABLE
 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\*---------------------------------------------------------------------------*/
#pragma once

#include <QString.h>
#include <QList>
#include <QStringList>
#include <QMap>
#include "patherimplementation.h"


// forward declarations
class SliceStack;
class PatherProgressCallback;
class Pather;
class PathStack;


/**
 * This object should be used to interface with a particular implementation
 * of a pather.  It must be aware of all pather types, so whenever a new
 * pather type is added it should be inserted into the enumeration and linked
 * in the internal makePather() method.
 *
 * Common pather parameters include:
 *  PathWidth - How wide the tool tip is for which the slices should be pathed
 *  MinPathLength (TODO) - Eliminate paths shorter than this length
 */
class PatherInterface {
public:

  /**
   * Returns a list of the names of the different pather implementations.  To get
   * the implementation to use, pass the desired index into getImplementation
   */
  static QStringList allPatherImplementations();

  /**
   * Returns the string-name of the specified implementation
   */
  static QString getPatherName(PatherImplementation implementation);

  /**
   * Starting at 0, this will return all implementations that can be selected
   * for use during pathing at run-time.  This is some set smaller than
   * all of the pathers, since it excludes all debugging and invalid
   * pathers.
   */
  static PatherImplementation getImplementation(int implementation_index);


public:

  /**
   * Initializes this pather interface to use a specific kind of pathing
   * implementation.  If the value doesn't specify a valid pather, none
   * of the methods in this class will work.
   */
  PatherInterface(PatherImplementation impl);
  ~PatherInterface();

  /**
   * Used to change parameter values used by the pather. float implementation
   */
  void set(const QString& name, float value);

  /**
   * Used to change parameter values used by the pather. int implementation
   */
  void set(const QString& name, int value);

  /**
   * Used to change parameter values used by the pather. bool implementation
   */
  void set(const QString& name, bool value);

  /**
   * Used to change parameter values used by the pather. QString implementation
   */
  void set(const QString& name, const QString& value);

  /**
   * Executes the pathing algorithm chosen for this class on a set of
   * slices.  The callback is periodically invoked while pathing
   * executes in order to report on its progress.  If pathing is
   * successful, this method returns true.  Otherwise, getLastErrorString
   * can be used to report what happened.
   * @see Pather::doPathing
   */
  bool doPathing(const SliceStack& slices,
                 PatherProgressCallback* callback);

  /**
   * Returns a string based on the error that occurred during the last
   * attempt at doPathing.  If doPathing succeeded (returned true) then
   * this will report either a blank string or that there was no error.
   */
  QString getLastErrorString() const;

  /**
   * Obtains the set of paths that were generated by this pather
   */
  const PathStack& getPathStack() const;

private:

  /**
   * Constructs a new instance of some specific type of pather.  This method
   * should return NULL if the implementation type couldn't be generated.
   */
  static Pather* makePather(PatherImplementation impl);


private:
  Pather* pather_;  /// holds the pather that was selected by the constructor
};

